// config/test.js - 测试环境配置
module.exports = {
    envs: {
      // 测试站点配置
      SQ_SITE_NAME: "SQTracker Test",
      SQ_SITE_DESCRIPTION: "Test Instance for API Testing",
      
      // 自定义主题（测试用默认值）
      SQ_CUSTOM_THEME: {
        primary: "#f45d48"
      },
      
      // 注册模式 - 测试时开放注册
      SQ_ALLOW_REGISTER: "open",
      
      // 允许匿名上传（测试时关闭）
      SQ_ALLOW_ANONYMOUS_UPLOADS: false,
      
      // 比率设置（测试时放宽限制）
      SQ_MINIMUM_RATIO: 0.5,
      SQ_MAXIMUM_HIT_N_RUNS: 5,
      
      // 种子分类（简化测试配置）
      SQ_TORRENT_CATEGORIES: {
        Movies: ["WebDL", "BluRay", "HDRip"],
        TV: ["WebDL", "HDTV"],
        Music: ["MP3", "FLAC"],
        Books: ["PDF", "EPUB"]
      },
      
      // 积分系统（测试友好的值）
      SQ_BP_EARNED_PER_GB: 10,
      SQ_BP_EARNED_PER_FILLED_REQUEST: 100,
      SQ_BP_COST_PER_INVITE: 1000,
      SQ_BP_COST_PER_GB: 100,
      
      // 站点范围免费（测试时关闭）
      SQ_SITE_WIDE_FREELEECH: false,
      
      // 允许未注册用户查看（测试时关闭）
      SQ_ALLOW_UNREGISTERED_VIEW: false,
      
      // 黑名单扩展名
      SQ_EXTENSION_BLACKLIST: ["exe", "bat", "com", "scr"],
      
      // 默认语言
      SQ_SITE_DEFAULT_LOCALE: "en",
      
      // URL 配置（测试环境）
      SQ_BASE_URL: "http://localhost:3000",
      SQ_API_URL: "http://localhost:3001",
      
      // 测试数据库（使用内存数据库）
      SQ_MONGO_URL: "mongodb://localhost:27017/sqtracker_test",
      
      // 禁用邮件（测试时总是禁用）
      SQ_DISABLE_EMAIL: true,
      
      // 邮件配置（测试时不需要，但保留结构）
      SQ_MAIL_FROM_ADDRESS: "test@sqtracker.dev",
      SQ_SMTP_HOST: "localhost",
      SQ_SMTP_PORT: 1025,
      SQ_SMTP_SECURE: false
    },
    secrets: {
      // 测试用的 JWT 密钥
      SQ_JWT_SECRET: "test_jwt_secret_key_for_testing_only_do_not_use_in_production",
      
      // 测试用的服务器密钥
      SQ_SERVER_SECRET: "test_server_secret_key_for_testing_only",
      
      // 测试管理员邮箱
      SQ_ADMIN_EMAIL: "admin@test.sqtracker.dev",
      
      // SMTP 凭证（测试时不需要）
      SQ_SMTP_USER: "test_user",
      SQ_SMTP_PASS: "test_password"
    }
  };
  
  // tests/setup-test-env.js - 测试环境设置脚本
  const path = require('path');
  const fs = require('fs');
  
  // 设置测试环境变量
  process.env.NODE_ENV = 'test';
  
  // 加载测试配置
  const testConfig = require('../config/test');
  
  // 将配置应用到环境变量
  Object.assign(process.env, testConfig.envs, testConfig.secrets);
  
  // 确保测试目录存在
  const testDirs = [
    'tests',
    'tests/helpers',
    'tests/fixtures',
    'test-reports',
    'coverage'
  ];
  
  testDirs.forEach(dir => {
    const dirPath = path.join(process.cwd(), dir);
    if (!fs.existsSync(dirPath)) {
      fs.mkdirSync(dirPath, { recursive: true });
      console.log(`✅ Created directory: ${dir}`);
    }
  });
  
  // 创建 .babelrc.test.js 文件
  const babelConfig = {
    presets: [
      ['@babel/preset-env', {
        targets: { node: 'current' }
      }]
    ],
    plugins: []
  };
  
  const babelTestConfigPath = path.join(process.cwd(), '.babelrc.test.js');
  if (!fs.existsSync(babelTestConfigPath)) {
    fs.writeFileSync(
      babelTestConfigPath,
      `module.exports = ${JSON.stringify(babelConfig, null, 2)};`
    );
    console.log('✅ Created .babelrc.test.js');
  }
  
  // 创建 jest.config.js 文件
  const jestConfig = {
    testEnvironment: 'node',
    setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
    testMatch: ['<rootDir>/tests/**/*.test.js'],
    collectCoverageFrom: [
      'src/**/*.js',
      '!src/index.js',
      '!src/server.js',
      '!src/setup/**',
      '!src/migrations/**',
      '!**/node_modules/**'
    ],
    coverageDirectory: 'coverage',
    coverageReporters: ['text', 'lcov', 'html', 'json'],
    coverageThreshold: {
      global: {
        branches: 70,
        functions: 70,
        lines: 70,
        statements: 70
      }
    },
    testTimeout: 30000,
    maxWorkers: 2,
    transform: {
      '^.+\\.js$': ['babel-jest', {
        configFile: './.babelrc.test.js'
      }]
    },
    moduleFileExtensions: ['js', 'json'],
    testPathIgnorePatterns: ['/node_modules/', '/coverage/'],
    bail: false,
    verbose: true,
    detectOpenHandles: true,
    forceExit: true
  };
  
  const jestConfigPath = path.join(process.cwd(), 'jest.config.js');
  if (!fs.existsSync(jestConfigPath)) {
    fs.writeFileSync(
      jestConfigPath,
      `module.exports = ${JSON.stringify(jestConfig, null, 2)};`
    );
    console.log('✅ Created jest.config.js');
  }
  
  console.log('🎯 Test environment setup completed!');
  console.log('📊 You can now run: npm run test');
  
  // tests/adapted-setup.js - 适配的测试设置
  require('@babel/register')({
    presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
  });
  
  const { MongoMemoryServer } = require('mongodb-memory-server');
  const mongoose = require('mongoose');
  
  let mongoServer;
  
  // 全局测试设置
  beforeAll(async () => {
    console.log('🚀 Starting test environment...');
    
    // 启动内存 MongoDB 实例
    mongoServer = await MongoMemoryServer.create({
      instance: {
        port: 27018, // 使用不同端口避免冲突
        dbName: 'sqtracker_test'
      }
    });
    
    const mongoUri = mongoServer.getUri();
    console.log(`📁 Test MongoDB URI: ${mongoUri}`);
    
    // 关闭现有连接
    if (mongoose.connection.readyState !== 0) {
      await mongoose.disconnect();
    }
    
    // 连接到测试数据库
    await mongoose.connect(mongoUri, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useFindAndModify: false,
      useCreateIndex: true
    });
    
    console.log('✅ Connected to test database');
    
    // 设置测试环境变量
    const testConfig = require('../config/test');
    Object.assign(process.env, testConfig.envs, testConfig.secrets);
    
    // 覆盖数据库 URL 为内存数据库
    process.env.SQ_MONGO_URL = mongoUri;
    
    console.log('🔧 Test environment variables set');
  }, 60000);
  
  // 全局测试清理
  afterAll(async () => {
    console.log('🧹 Cleaning up test environment...');
    
    try {
      // 断开数据库连接
      if (mongoose.connection.readyState !== 0) {
        await mongoose.disconnect();
        console.log('✅ Disconnected from test database');
      }
      
      // 停止内存 MongoDB 实例
      if (mongoServer) {
        await mongoServer.stop();
        console.log('✅ Stopped test MongoDB server');
      }
    } catch (error) {
      console.error('❌ Error during cleanup:', error);
    }
  }, 10000);
  
  // 每个测试后清理数据库
  afterEach(async () => {
    if (mongoose.connection.readyState === 1) {
      const collections = mongoose.connection.collections;
      
      for (const key in collections) {
        const collection = collections[key];
        try {
          await collection.deleteMany({});
        } catch (error) {
          console.warn(`Warning: Failed to clear collection ${key}:`, error.message);
        }
      }
    }
  });
  
  // 添加自定义匹配器
  expect.extend({
    toBeValidObjectId(received) {
      const isValid = mongoose.Types.ObjectId.isValid(received);
      return {
        message: () => `expected ${received} to be a valid ObjectId`,
        pass: isValid,
      };
    },
    
    toHaveValidJWT(received) {
      const jwt = require('jsonwebtoken');
      try {
        jwt.verify(received, process.env.SQ_JWT_SECRET);
        return {
          message: () => `expected ${received} to be a valid JWT`,
          pass: true,
        };
      } catch (error) {
        return {
          message: () => `expected ${received} to be a valid JWT, but got error: ${error.message}`,
          pass: false,
        };
      }
    },
    
    toHaveValidTorrentData(received) {
      const requiredFields = ['name', 'infoHash', 'size', 'uploadedBy'];
      const hasAllFields = requiredFields.every(field => received.hasOwnProperty(field));
      
      return {
        message: () => `expected torrent object to have required fields: ${requiredFields.join(', ')}`,
        pass: hasAllFields,
      };
    }
  });
  
  // 全局错误处理
  process.on('unhandledRejection', (reason, promise) => {
    console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  });
  
  process.on('uncaughtException', (error) => {
    console.error('Uncaught Exception:', error);
  });
  
  console.log('🎯 Test setup loaded successfully');
  
  // tests/helpers/adapted-testData.js - 适配的测试数据
  const crypto = require('crypto');
  
  const generateAdaptedTestData = () => ({
    users: {
      admin: {
        username: 'admin',
        email: 'admin@test.sqtracker.dev',
        password: 'admin123!@#',
        role: 'admin',
        emailVerified: true,
        bonusPoints: 10000,
        remainingInvites: 10
      },
      
      regularUser: {
        username: 'testuser1',
        email: 'user1@test.sqtracker.dev',
        password: 'password123!@#',
        role: 'user',
        emailVerified: true,
        bonusPoints: 1000,
        remainingInvites: 3
      },
      
      newUser: {
        username: 'newuser',
        email: 'newuser@test.sqtracker.dev',
        password: 'newpass123!@#',
        role: 'user',
        emailVerified: false,
        bonusPoints: 0,
        remainingInvites: 0
      }
    },
    
    torrents: {
      movieBluRay: {
        name: 'Test Movie 2023 BluRay 1080p',
        description: 'A fantastic test movie in high quality BluRay format',
        type: 'Movies',
        source: 'BluRay',
        infoHash: crypto.randomBytes(20).toString('hex'),
        binary: Buffer.from('fake torrent data for movie').toString('base64'),
        size: 8589934592, // 8GB
        files: [
          { path: 'Test.Movie.2023.1080p.BluRay.x264.mkv', size: 8000000000 },
          { path: 'Subtitles/English.srt', size: 100000 },
          { path: 'Subtitles/Chinese.srt', size: 120000 }
        ],
        tags: ['action', 'thriller', '1080p', 'x264'],
        poster: 'https://example.com/poster.jpg',
        mediaInfo: 'Video: H.264, 1920x1080, 23.976 fps\nAudio: DTS, 6 channels'
      },
      
      tvShowWebDL: {
        name: 'Test TV Show S01E01 WebDL 720p',
        description: 'First episode of the amazing test TV series',
        type: 'TV',
        source: 'WebDL',
        infoHash: crypto.randomBytes(20).toString('hex'),
        binary: Buffer.from('fake torrent data for tv show').toString('base64'),
        size: 2147483648, // 2GB
        files: [
          { path: 'Test.TV.Show.S01E01.720p.WebDL.x264.mkv', size: 2000000000 },
          { path: 'Subtitles.srt', size: 80000 }
        ],
        tags: ['drama', 'comedy', '720p', 'webseries'],
        poster: 'https://example.com/tv-poster.jpg'
      },
      
      musicAlbum: {
        name: 'Test Artist - Test Album (2023) [FLAC]',
        description: 'Complete studio album in lossless FLAC format',
        type: 'Music',
        source: 'CD',
        infoHash: crypto.randomBytes(20).toString('hex'),
        binary: Buffer.from('fake torrent data for music').toString('base64'),
        size: 536870912, // 512MB
        files: [
          { path: '01 - Track One.flac', size: 45000000 },
          { path: '02 - Track Two.flac', size: 42000000 },
          { path: '03 - Track Three.flac', size: 48000000 },
          { path: 'cover.jpg', size: 500000 },
          { path: 'info.txt', size: 2048 }
        ],
        tags: ['rock', 'alternative', 'flac', '2023']
      }
    },
    
    ratings: {
      excellent: { score: 5, comment: 'Absolutely perfect! Amazing quality and content.' },
      veryGood: { score: 4, comment: 'Very good torrent, recommended!' },
      good: { score: 3, comment: 'Good quality, meets expectations.' },
      poor: { score: 2, comment: 'Quality could be better.' },
      terrible: { score: 1, comment: 'Poor quality, not recommended.' }
    },
    
    announcements: {
      siteUpdate: {
        title: 'Major Site Update - New Features Added',
        body: `We are excited to announce several new features:
        
  • Enhanced search functionality
  • Improved torrent recommendation system  
  • New rating system for better quality control
  • Performance optimizations
  
  Please report any issues to the admin team.`,
        pinned: true,
        allowComments: true
      },
      
      maintenanceNotice: {
        title: 'Scheduled Maintenance Window',
        body: 'The site will undergo maintenance on Sunday 2AM-4AM UTC. Please plan your downloads accordingly.',
        pinned: false,
        allowComments: true
      },
      
      rulesUpdate: {
        title: 'Updated Community Rules',
        body: 'Please review the updated community guidelines in the wiki section.',
        pinned: true,
        allowComments: false
      }
    },
    
    requests: {
      movieRequest: {
        title: 'Request: Latest Blockbuster Movie 2023',
        body: `Looking for the latest blockbuster movie in the following specs:
        
  • Quality: 1080p or 4K
  • Format: BluRay or WebDL
  • Audio: Multi-language preferred
  • Subtitles: English and Chinese
  
  Will seed for long term. Thanks!`
      },
      
      tvSeriesRequest: {
        title: 'Request: Complete TV Series Collection',
        body: 'Requesting complete seasons 1-5 of the popular drama series. Any quality above 720p is acceptable.'
      },
      
      musicRequest: {
        title: 'Request: Rare Music Album Collection',
        body: 'Looking for rare albums from the 90s in FLAC format. Will provide detailed list if someone can help.'
      }
    },
    
    comments: {
      positive: 'Great upload! Thanks for sharing this high-quality content.',
      technical: 'Video: Excellent quality, Audio: Clear, Subtitles: Well-synced. Recommended!',
      question: 'Does this include the director commentary track?',
      appreciation: 'Been looking for this for months. Much appreciated!',
      issue: 'Having trouble with the download, seems to be stuck at 99%.'
    },
    
    progressData: {
      downloading: {
        uploaded: { total: 0, session: 0 },
        downloaded: { total: 1073741824, session: 1073741824 }, // 1GB
        left: 1073741824 // 1GB remaining
      },
      
      seeding: {
        uploaded: { total: 5368709120, session: 2147483648 }, // 5GB total, 2GB this session
        downloaded: { total: 2147483648, session: 0 }, // 2GB total
        left: 0 // Complete
      },
      
      completed: {
        uploaded: { total: 2147483648, session: 0 }, // 2GB
        downloaded: { total: 2147483648, session: 0 }, // 2GB
        left: 0 // Complete
      }
    }
  });
  
  module.exports = { generateAdaptedTestData };
  
  // package-scripts.js - 项目脚本管理
  const scripts = {
    // 测试相关脚本
    test: {
      default: 'npm run test:setup && jest --detectOpenHandles',
      watch: 'jest --watch --detectOpenHandles',
      coverage: 'jest --coverage --detectOpenHandles',
      ci: 'jest --coverage --ci --watchAll=false --detectOpenHandles',
      verbose: 'jest --verbose --detectOpenHandles',
      silent: 'jest --silent --detectOpenHandles',
      performance: 'node tests/performance.test.js',
      security: 'jest tests/security.test.js',
      report: 'node tests/report-generator.js',
      all: 'npm run test:coverage && npm run test:performance && npm run test:report',
      setup: 'node tests/setup-test-env.js'
    },
    
    // 代码质量脚本
    lint: {
      default: 'eslint src/**/*.js',
      test: 'eslint tests/**/*.js',
      fix: 'eslint src/**/*.js tests/**/*.js --fix',
      check: 'eslint src/**/*.js tests/**/*.js'
    },
    
    // 数据库脚本
    db: {
      migrate: 'babel-node src/migrations/torrent-add-fuzzy-name.js',
      seed: 'babel-node tests/helpers/seed-test-data.js',
      reset: 'babel-node tests/helpers/reset-test-db.js'
    },
    
    // 开发脚本
    dev: {
      default: 'nodemon --exec babel-node src/index.js',
      test: 'NODE_ENV=test nodemon --exec babel-node src/index.js',
      debug: 'NODE_ENV=development DEBUG=* nodemon --exec babel-node src/index.js'
    }
  };
  
  module.exports = scripts;